package com.company.nuwa.mybatis.generator.plugins;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.internal.util.StringUtility;

import java.util.Properties;

/**
 * <p>转换类</p>
 *
 * @author lili
 * @version 1.0: ConverterPlugin
 * @date 2023/9/16 17:03
 */
public class ConverterPlugin {

    public static GeneratedJavaFile convertFile(IntrospectedTable introspectedTable,
                                                Context context) {
        Properties contextProperties = context.getProperties();
        String applicationName = contextProperties.getProperty("applicationName");
        String contextPath = contextProperties.getProperty("contextPath");
        String domainObjectName = introspectedTable.getFullyQualifiedTable().getDomainObjectName();
        StringBuilder builder = new StringBuilder();
        FullyQualifiedJavaType mapperType = new FullyQualifiedJavaType(
            introspectedTable.getMyBatis3JavaMapperType());
        Interface requestClass = new Interface(builder.delete(0, builder.length())
            .append(
                mapperType.getPackageName().replace(".mapper", "").replace("domain", "converter"))
            .append(".").append(domainObjectName).append("Converter").toString());
        requestClass.setVisibility(JavaVisibility.PUBLIC);
        context.getCommentGenerator().addJavaFileComment(requestClass);
        String basePage = mapperType.getPackageName();
        //添加domain的import
        requestClass.addImportedType(new FullyQualifiedJavaType(ApiExtPluginUtils.transformPackagePaths(basePage, ".request",".*")));
        requestClass.addImportedType(new FullyQualifiedJavaType(ApiExtPluginUtils.transformPackagePaths(basePage, ".dto",".*")));
        requestClass.addImportedType(new FullyQualifiedJavaType(ApiExtPluginUtils.transformPackagePaths(basePage, ".domain",".model.*")));
        //添加domain的import
        requestClass.addImportedType(new FullyQualifiedJavaType("org.mapstruct.MappingTarget"));
        requestClass.addImportedType(new FullyQualifiedJavaType("org.mapstruct.Mapper"));
        requestClass.addImportedType(new FullyQualifiedJavaType("org.mapstruct.NullValuePropertyMappingStrategy"));
        requestClass.addImportedType(new FullyQualifiedJavaType("org.mapstruct.BeanMapping"));

        requestClass.addImportedType(new FullyQualifiedJavaType("javax.annotation.Generated"));
        requestClass.addImportedType(new FullyQualifiedJavaType("java.util.List"));
        requestClass.addImportedType(new FullyQualifiedJavaType("com.github.pagehelper.PageInfo"));


        requestClass.addJavaDocLine("/**");
        String remarks = introspectedTable.getRemarks();
        if (StringUtility.stringHasValue(remarks)) {
            String[] remarkLines = remarks.split(System.getProperty("line.separator"));
            for (String remarkLine : remarkLines) {
                requestClass.addJavaDocLine(" * <p>" + remarkLine + "转换类</p>");
            }
        }

        StringBuilder sb = new StringBuilder();
        sb.append(" * @author ").append(System.getProperties().getProperty("user.name"));
        requestClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * ").append("@version 1.0:")
            .append(introspectedTable.getFullyQualifiedTable().getDomainObjectName())
            .append("Converter").append(".java");
        requestClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * @date ");
        sb.append(ApiExtPluginUtils.getDateString());
        requestClass.addJavaDocLine(sb.toString());
        requestClass.addJavaDocLine(" */");
        requestClass.addAnnotation("@Mapper(componentModel = \"spring\")");
        //增加方法
        //SysCity convert(SysCityAddRequest from)
        addMethod(domainObjectName, requestClass);
        updateMethod(domainObjectName, requestClass);
        convertMethod(domainObjectName, requestClass);
        convert2ListMethod(domainObjectName, requestClass);
        convert2PageMethod(domainObjectName, requestClass);
        // void convert(SysCityUpdateRequest from, @MappingTarget SysCity to);

        // SysCityDTO convert(SysCity record);
        GeneratedJavaFile generatedJavaFile = new GeneratedJavaFile(requestClass,
            context.getJavaModelGeneratorConfiguration().getTargetProject(),
            context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
            context.getJavaFormatter());
        return generatedJavaFile;
    }

    //SysCity convert(SysCityAddRequest from)
    public static void addMethod(String domainObjectName, Interface requestClass) {
        Method method = new Method("convert");
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setAbstract(true);
        method.setReturnType(new FullyQualifiedJavaType(domainObjectName));
        Parameter addParameter = new Parameter(
            new FullyQualifiedJavaType(domainObjectName + "AddRequest"), "from");
        method.addParameter(addParameter);
        method.addAnnotation("@Generated(\"org.mybatis.generator.api.MyBatisGenerator\")");
        requestClass.addMethod(method);
    }

    public static void updateMethod(String domainObjectName, Interface requestClass) {
        Method method = new Method("convert");
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setAbstract(true);
        Parameter fromParameter = new Parameter(
            new FullyQualifiedJavaType(domainObjectName + "UpdateRequest"), "from");
        method.addParameter(fromParameter);
        Parameter toParameter = new Parameter(new FullyQualifiedJavaType(domainObjectName), "to");
        toParameter.addAnnotation("@MappingTarget");
        method.addParameter(toParameter);
        method.addAnnotation("@Generated(\"org.mybatis.generator.api.MyBatisGenerator\")");
        method.addAnnotation("@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)");
        requestClass.addMethod(method);
    }

    public static void convertMethod(String domainObjectName, Interface requestClass) {
        Method method = new Method("convert");
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setAbstract(true);
        method.setReturnType(new FullyQualifiedJavaType(domainObjectName + "DTO"));
        Parameter addParameter = new Parameter(new FullyQualifiedJavaType(domainObjectName),
            "from");
        method.addParameter(addParameter);
        method.addAnnotation("@Generated(\"org.mybatis.generator.api.MyBatisGenerator\")");
        requestClass.addMethod(method);
    }

    public static void convert2ListMethod(String domainObjectName, Interface requestClass) {
        Method method = new Method("convert");
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setAbstract(true);
        method.setReturnType(new FullyQualifiedJavaType("List<" + domainObjectName + "DTO" + ">"));
        Parameter addParameter = new Parameter(
            new FullyQualifiedJavaType("List<" + domainObjectName + ">"), "from");
        method.addParameter(addParameter);
        method.addAnnotation("@Generated(\"org.mybatis.generator.api.MyBatisGenerator\")");
        requestClass.addMethod(method);
    }

    public static void convert2PageMethod(String domainObjectName, Interface requestClass) {
        Method method = new Method("convertPage");
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setAbstract(true);
        method.setReturnType(new FullyQualifiedJavaType("PageInfo<" + domainObjectName + "DTO" + ">"));
        Parameter addParameter = new Parameter(
                new FullyQualifiedJavaType("PageInfo<" + domainObjectName + ">"), "from");
        method.addParameter(addParameter);
        method.addAnnotation("@Generated(\"org.mybatis.generator.api.MyBatisGenerator\")");
        requestClass.addMethod(method);
    }
}
